package com.gr.jron.util;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertyFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.jdbc.BatchingBatcher;
import org.hibernate.jdbc.JDBCContext;
import org.hibernate.jdbc.ConnectionManager;
import org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer;
import org.hibernate.impl.SessionImpl;
import org.apache.commons.dbcp.PoolingDataSource;


/**
 * Created by Jronrun.
 * User: jron
 * Date: 2007-9-28
 * Time: 13:26:40
 * It's jron's dream to cqiu
 */
public class ServletTools {

    /**
     * for mootools json.remote
     *
     * @param msgTitle
     * @param msgBody
     * @param response
     * @throws Exception
     */
    public static void jsonMsgResponse(String msgTitle, String msgBody, HttpServletResponse response, boolean isSuccess) throws Exception {
        response.setContentType("text/html;charset=utf-8");
        response.setHeader("Cache-Control", "no-cache");
        PrintWriter out = response.getWriter();
        out.print("{msgTitle:'" + msgTitle + "',msgBody:'" + msgBody + "',isSuccess:'" + isSuccess + "'}");
        out.close();
    }

    /**
     * For a success message:
     * {"success":true,"info":"Added Successfully."}
     * <p/>
     * For a failure:
     * {"success":false,"errorInfo":"Failed to add."}
     * <p/>
     * -- may another way:
     * try {
     * usersService.save(user);
     * response.getWriter().print("{success:true,info:'jronsuccess'}");
     * } catch (Exception e) {
     * e.printStackTrace();
     * response.getWriter().print("{failure:true,info:'" + e.getMessage() + "'}");
     * }
     * <p/>
     * form_instance_create.submit({
     * waitMsg:'waiting',
     * reset: false,
     * failure: function(form_instance_create, action) {
     * Ext.MessageBox.alert('hhhhhha', action.result.info);
     * },
     * success: function(form_instance_create, action) {
     * Ext.MessageBox.alert('ttttttt', action.result.info);
     * <p/>
     * for EXT msg
     */
    public static void jsonMsgResponse(String msg, HttpServletResponse response,
                                       String callback, boolean isSuccess) throws Exception {
        boolean scriptTag = false;
        if (callback != null) {
            scriptTag = true;
            response.setContentType("text/javascript;charset=utf-8");
        } else {
            response.setContentType("application/x-json;charset=utf-8");
        }
        response.setHeader("Cache-Control", "no-cache");

        PrintWriter out = response.getWriter();
        if (scriptTag) out.write(callback + "(");
        if (isSuccess) out.print("{success:true,info:'" + msg + "'}");
        if (!isSuccess) out.print("{success:false,errorInfo:'" + msg + "'}");
        if (scriptTag) out.write(");");
        out.close();
    }

    /**
     * for EXT
     *
     * @param jsonData
     * @param response
     * @param callback
     * @param isSingleObj
     * @throws Exception
     */
    public static void jsonResponse(JSONObject jsonData, HttpServletResponse response,
                                    String callback, boolean isSingleObj) throws Exception {
        // check whether it is script Tag...
        // which is called by JSON
        boolean scriptTag = false;
        if (callback != null) {
            scriptTag = true;
            response.setContentType("text/javascript;charset=utf-8");
        } else {
            response.setContentType("application/x-json;charset=utf-8");
        }
        response.setHeader("Cache-Control", "no-cache");

        PrintWriter out = response.getWriter();
        if (scriptTag) out.write(callback + "(");
        if (isSingleObj) out.write("[");
        out.print(jsonData);
        if (isSingleObj) out.write("]");
        if (scriptTag) out.write(");");
        out.close();
    }

    /**
     * for EXT
     *
     * @param data
     * @param totalCount
     * @return
     */
    public static JSONObject jsonExtGridBackendReturn(List data, int totalCount) {
        JSONArray jsonArray = JSONArray.fromObject(data, hibernateJsonConfig());
        Map map = new HashMap();
        map.put("totalCount", totalCount);
        map.put("results", jsonArray);

        return JSONObject.fromObject(map);
    }

    public static String getRealIp(HttpServletRequest request) throws Exception {
        String ip;
        ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    /**
     * 防止通过hibernate返回对象实例时 出现
     * Property 'transactionTimeout' has no read method. SKIPPED 异常的非正规(I think)解决方法
     *
     * serializing a recently hydrated instance coming from a database with Hibernate,
     *  because the instance's class is not exactly the one you expect
     * (it actually is a cglib proxy class) the default class matching mechanism will not work.
     * @return
     */
    public static JsonConfig hibernateJsonConfig() {
        JsonConfig jsonConfig = new JsonConfig();
        jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
            public boolean apply(Object source, String name, Object value) {
                return value != null && BatchingBatcher.class.isAssignableFrom(value.getClass())
                        || value != null && CGLIBLazyInitializer.class.isAssignableFrom(value.getClass())
                        || value != null && SessionImpl.class.isAssignableFrom(value.getClass())
                        || value != null && JDBCContext.class.isAssignableFrom(value.getClass())
                        || value != null && ConnectionManager.class.isAssignableFrom(value.getClass())
                        || value != null && PoolingDataSource.class.isAssignableFrom(value.getClass());
            }
        });
        return jsonConfig;
    }

}
